package com.lwj.widget.viewpagerindicator;

import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.PageSlider;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.render.Path;
import ohos.agp.utils.Color;
import ohos.agp.utils.Point;
import ohos.agp.utils.RectFloat;
import ohos.app.Context;

/**
 * 绘制指示器(方法描述)
 *
 * @author wangpeng
 * @since 2021-03-20
 */
public class ViewPagerIndicator extends Component implements Component.DrawTask {
    // 默认半径
    private static final float DEFAULTVALUE = 20f;

    // 默认指示器数量
    private static final int DEFAULTINDIATORNUM = 0;

    // 默认线宽
    private static final int DEFAULTSTROKEWIDTH = 3;

    // 一个常量，用来计算绘制圆形贝塞尔曲线控制点的位置
    private static final float M = 0.551915024494f;

    // 路径
    private Path mPath;

    // 实心画笔
    private Paint paintFill;

    // 空心画笔
    private Paint paintStroke;

    // 个数
    private int mNum;

    // 半径
    private double mRadius;

    // 选中半径，默认为mRadius
    private double mRadiusSelected;

    // 线长
    private double mLength;

    // 偏移量
    private double mOffset;

    // 选中颜色
    private Color mSelectedColor;

    // 默认颜色
    private Color mDefaultColor;

    // 点类型
    private int mIndicatorType;

    // 距离类型
    private int mDistanceType;

    // 间隔距离
    private double mDistance;

    // 第几张
    private int mPosition;

    // 百分比
    private double mPercent;

    // 是否往回滑动
    private boolean isLeft;

    // 是否需要动画
    private boolean isAnimation;

    private MinePoint[] mControlPoint = new MinePoint[9];

    private MinePoint[] mSpringPoint = new MinePoint[6];

    private CenterPoint mCenterPoint = new CenterPoint();

    /**
     * 构造函数
     *
     * @param context
     * @param attrs
     */
    public ViewPagerIndicator(Context context, AttrSet attrs) {
        super(context, attrs);
        setStyleable(context, attrs);
        initPaint();
    }

    /**
     * xml 参数设置  选中颜色 默认颜色  点大小 长度 距离 距离类型 类型 真实个数(轮播)
     *
     * @param context
     * @param attrs
     */
    private void setStyleable(Context context, AttrSet attrs) {
        mDefaultColor = Utils.getInstance().getAttrColorValue(attrs, "vpi_default_color", Color.GREEN);
        mSelectedColor = Utils.getInstance().getAttrColorValue(attrs, "vpi_selected_color", mDefaultColor);
        mRadius = Utils.getInstance().getAttrFloatValue(attrs, "vpi_radius", DEFAULTVALUE);
        mRadiusSelected = Utils.getInstance().getAttrFloatValue(attrs, "vpi_radius_selected", (float) mRadius);
        mLength = Utils.getInstance().getAttrFloatValue(attrs, "vpi_length", (float) (mRadius + mRadius));
        mDistance = Utils.getInstance().getAttrFloatValue(attrs, "vpi_distance", (float) mLength);

        // 指示器的数量,默认为4
        mNum = Utils.getInstance().getAttrIntValue(attrs, "vpi_num", DEFAULTINDIATORNUM);
        isAnimation = Utils.getInstance().getAttrBoolValue(attrs, "vpi_animation", true);
        mIndicatorType = Utils.getInstance().getAttrIntValue(attrs, "vpi_indicatorType", IndicatorType.CIRCLE);
        mDistanceType = Utils.getInstance().getAttrIntValue(attrs, "vpi_distanceType", DistanceType.BY_RADIUS);
        switch (mIndicatorType) {
            case IndicatorType.BEZIER:
                mControlPoint = new MinePoint[]{new MinePoint(), new MinePoint(), new MinePoint(), new MinePoint(),
                        new MinePoint(), new MinePoint(), new MinePoint(), new MinePoint(), new MinePoint(),
                        new MinePoint(), new MinePoint(), new MinePoint()};
                break;
            case IndicatorType.SPRING:
                mSpringPoint = new MinePoint[]{new MinePoint(), new MinePoint(), new MinePoint(), new MinePoint(),
                        new MinePoint(), new MinePoint()};
                break;
            default:
                break;
        }
        invalidate();
    }

    /**
     * 初始化画笔
     */
    private void initPaint() {
        paintStroke = new Paint();
        paintFill = new Paint();
        mPath = new Path();

        // 实心
        paintFill.setStyle(Paint.Style.FILLANDSTROKE_STYLE);
        paintFill.setColor(mSelectedColor);
        paintFill.setAntiAlias(true);
        paintFill.setStrokeWidth(DEFAULTSTROKEWIDTH);

        // 空心
        paintStroke.setStyle(Paint.Style.FILL_STYLE);
        paintStroke.setColor(mDefaultColor);
        paintStroke.setAntiAlias(true);
        paintStroke.setStrokeWidth(DEFAULTSTROKEWIDTH);
    }

    /**
     * 初始化
     */
    @Override
    public void invalidate() {
        super.invalidate();
        addDrawTask(this::onDraw);
    }

    /**
     * 绘制 invalidate()后 执行
     *
     * @param component
     * @param canvas
     */
    @Override
    public void onDraw(Component component, Canvas canvas) {
        if (mNum <= 0) {
            return;
        }
        int width = getWidth();
        int height = getHeight();
        canvas.translate(width / 2f, height / 2f);

        // 初始化画笔
        initPaint();

        // 距离
        switch (mDistanceType) {
            case DistanceType.BY_DISTANCE:
                break;
            case DistanceType.BY_RADIUS: // 圆心到 3倍半径 只有一个半径

                mDistance = 3 * mRadius;
                break;
            case DistanceType.BY_LAYOUT: // 布局等分
                if (mIndicatorType == IndicatorType.CIRCLE_LINE) {
                    mDistance = (width / (float)(mNum + 1));
                } else {
                    mDistance = (width / (float) mNum);
                }
                break;
        }

        switch (mIndicatorType) {
            // 圆
            case IndicatorType.CIRCLE:
                for (int ic = 0; ic < mNum; ic++) {
                    // 默认点 -(mNum - 1) * 0.5f * mDistance 第一个点
                    canvas.drawCircle((float)(-(mNum - 1) * 0.5f * mDistance + ic * mDistance), 0f, (float)mRadius, paintStroke);
                }
                // 选中
                canvas.drawCircle((float) (-(mNum - 1) * 0.5f * mDistance + mOffset), 0f, (float)mRadiusSelected, paintFill);
                break;

            // 线
            case IndicatorType.LINE:
                paintStroke.setStrokeWidth((float) mRadius);
                float startX = (float) (-(mNum - 1) * 0.5f * mDistance - mLength / 2);
                float stopX = (float) (-(mNum - 1) * 0.5f * mDistance + mLength / 2);

                // 默认
                for (int id = 0; id < mNum; id++) {
                    Point startPoint = new Point((float) (startX + id * mDistance), 0);
                    Point endPoint = new Point((float) (stopX + id * mDistance), 0);
                    canvas.drawLine(startPoint, endPoint, paintStroke);
                }

                // 选中
                paintFill.setStrokeWidth((float) mRadius);
                float startF = (float) (-(mNum - 1) * 0.5f * mDistance - mLength / 2 + mOffset);
                float stopF = (float) (-(mNum - 1) * 0.5f * mDistance + mLength / 2 + mOffset);
                Point mStartFPoint = new Point(startF, 0);
                Point mEndFPoint = new Point(stopF, 0);
                canvas.drawLine(mStartFPoint, mEndFPoint, paintFill);
                break;

            // 圆线
            case IndicatorType.CIRCLE_LINE:
                // 最后一个 右滑
                if (mPosition == mNum - 1) {
                    // 第一个 线 选中 消失
                    float mLeftClose = (float) (-mNum * 0.5f * mDistance - mRadius);
                    float rightClose = (float) (mLeftClose + 2 * mRadius + mOffset);
                    float topClose = (float) -mRadius;
                    float bottomClose = (float) mRadius;

                    // 设置个新的长方形
                    RectFloat rectClose = new RectFloat(mLeftClose, topClose, rightClose, bottomClose);
                    canvas.drawRoundRect(rectClose, (float)mRadius, (float)mRadius, paintStroke);

                    // 最后一个 线  显示
                    float rightOpen = (float) (-mNum * 0.5f * mDistance + mNum * mDistance + mRadius);
                    float leftOpen = (float) (rightOpen - 2 * mRadius - mDistance + mOffset);
                    float topOpen = (float) -mRadius;
                    float bottomOpen = (float) mRadius;

                    // 设置个新的长方形
                    RectFloat rectOpen = new RectFloat(leftOpen, topOpen, rightOpen, bottomOpen);
                    canvas.drawRoundRect(rectOpen, (float)mRadius, (float)mRadius, paintStroke);

                    // 圆
                    for (int ic = 1; ic < mNum; ic++) {
                        canvas.drawCircle((float) (rightClose - mRadius + ic * mDistance), 0f, (float)mRadius, paintStroke);
                    }
                } else {
                    // 第一个 线 选中 消失
                    float leftClose = (float) (-mNum * 0.5f * mDistance + mPosition * mDistance - mRadius);
                    float rightClose = (float) (leftClose + 2 * mRadius + mDistance - mOffset);
                    float topClose = (float) -mRadius;
                    float bottomClose = (float) mRadius;

                    // 设置个新的长方形
                    RectFloat rectClose = new RectFloat(leftClose, topClose, rightClose, bottomClose);
                    canvas.drawRoundRect(rectClose, (float)mRadius, (float)mRadius, paintStroke);

                    // 第二个 线  显示
                    if (mPosition < mNum - 1) {
                        float rightOpen = (float) (-mNum * 0.5f * mDistance + (mPosition + 2) * mDistance + mRadius);
                        float leftOpen = (float) (rightOpen - 2 * mRadius - mOffset);
                        float topOpen = (float) -mRadius;
                        float bottomOpen = (float) mRadius;

                        // 设置个新的长方形
                        RectFloat rectOpen = new RectFloat(leftOpen, topOpen, rightOpen, bottomOpen);
                        canvas.drawRoundRect(rectOpen, (float)mRadius, (float)mRadius, paintStroke);
                    }

                    // 圆
                    for (int ic = mPosition + 3; ic <= mNum; ic++) {
                        canvas.drawCircle((float) (-mNum * 0.5f * mDistance + ic * mDistance), 0f, (float)mRadius, paintStroke);
                    }
                    for (int ic = mPosition - 1; ic >= 0; ic--) {
                        canvas.drawCircle((float) (-mNum * 0.5f * mDistance + ic * mDistance), 0f, (float)mRadius, paintStroke);
                    }
                }
                break;

            // 贝塞尔 弹性球
            case IndicatorType.BEZIER:
                for (int ic = 0; ic < mNum; ic++) {
                    // 默认点 -(mNum - 1) * 0.5f * mDistance 第一个点
                    canvas.drawCircle((float) (-(mNum - 1) * 0.5f * mDistance + ic * mDistance), 0f, (float)mRadius, paintStroke);
                }

                // 选中
                drawCubicBezier(canvas);
                break;

            // 贝塞尔 粘性球
            case IndicatorType.SPRING:
                for (int ic = 0; ic < mNum; ic++) { // 默认点 -(mNum - 1) * 0.5f * mDistance 第一个点
                    canvas.drawCircle((float) (-(mNum - 1) * 0.5f * mDistance + ic * mDistance), 0f, (float)mRadius, paintStroke);
                }
                drawSpringBezier(canvas);
                break;

            // 进度条
            case IndicatorType.PROGRESS:
                for (int ic = 0; ic < mNum; ic++) { // 默认点 -(mNum - 1) * 0.5f * mDistance 第一个点
                    canvas.drawCircle((float) (-(mNum - 1) * 0.5f * mDistance + ic * mDistance), 0f, (float)mRadius, paintStroke);
                }

                // 选中
                float rightOpen = (float) (-(mNum - 1) * 0.5f * mDistance + mOffset + mRadius);
                float leftOpen = (float) (-(mNum - 1) * 0.5f * mDistance - mRadius);
                float topOpen = (float) -mRadius;
                float bottomOpen = (float) mRadius;
                RectFloat rectOpen = new RectFloat(leftOpen, topOpen, rightOpen, bottomOpen); // 设置个新的长方形
                canvas.drawRoundRect(rectOpen, (float)mRadius, (float)mRadius, paintFill);
                break;
        }
    }

    /**
     * 绘制弹性
     *
     * @param canvas
     */
    private void drawSpringBezier(Canvas canvas) {
        // 右圆圆心
        double rightCircleX;

        // 右圆半径
        double rightCircleRadius;

        // 左圆圆心
        double leftCircleX;

        // 左圆半径
        double leftCircleRadius;

        // 最大半径
        double maxRadius = mRadius;

        // 最小半径
        double minRadius = mRadius / 2;

        // 控制点
        if (mPosition == mNum - 1 && !isLeft) { // 第一个 右滑  0---4
            if (mPercent <= 0.5) {
                rightCircleX = (float) (-(mNum - 1) * 0.5f * mDistance + (mNum - 1) * mDistance);
                leftCircleX = (float) (-(mNum - 1) * 0.5f * mDistance + (0.5f - mPercent) / 0.5f * (mNum - 1) * mDistance);
                rightCircleRadius = (float) (minRadius + (maxRadius - minRadius) * (0.5f - mPercent) / 0.5f);
            } else {
                rightCircleX = (float) (-(mNum - 1) * 0.5f * mDistance + (1f - mPercent) / 0.5f * (mNum - 1) * mDistance);
                leftCircleX = (float) (-(mNum - 1) * 0.5f * mDistance);
                rightCircleRadius = minRadius;
            }
            leftCircleRadius = (float) (mRadius * mPercent);
        } else if ((mPosition == mNum - 1) && isLeft) { // 最后一个 左滑 4--0
            // 0-1
            if (mPercent >= 0.5) { // 左亭
                leftCircleRadius = (float) (minRadius + (maxRadius - minRadius) * (-0.5f + mPercent) / 0.5f);
                leftCircleX = (float) (-(mNum - 1) * 0.5f * mDistance);
                rightCircleX = (float) (-(mNum - 1) * 0.5f * mDistance + (1 - mPercent) / 0.5f * (mNum - 1) * mDistance);
            } else { // 左动
                leftCircleRadius = minRadius;
                leftCircleX = (float) (-(mNum - 1) * 0.5f * mDistance + (0.5f - mPercent) / 0.5f * (mNum - 1) * mDistance);
                rightCircleX = (float) (-(mNum - 1) * 0.5f * mDistance + (mNum - 1) * mDistance);
            }
            rightCircleRadius = (float) (mRadius * (1 - mPercent));
        } else if (isLeft) { // 中间的 左滑
            mOffset = (mPercent + mPosition) * mDistance;
            if (mPercent >= 0.5) {
                leftCircleX = (float) (-(mNum - 1) * 0.5f * mDistance + ((mPercent - 0.5f) / 0.5f + mPosition) * mDistance);
                rightCircleX = (float) (-(mNum - 1) * 0.5f * mDistance + (1 + mPosition) * mDistance);
                rightCircleRadius = (float) (minRadius + (maxRadius - minRadius) * (mPercent - 0.5f) / 0.5f);
            } else {
                rightCircleX = (float) (-(mNum - 1) * 0.5f * mDistance + (mPercent / 0.5f + mPosition) * mDistance);
                leftCircleX = (float) (-(mNum - 1) * 0.5f * mDistance + mPosition * mDistance);
                rightCircleRadius = minRadius;
            }
            leftCircleRadius = (float) (mRadius * (1 - mPercent));
        } else { // 右滑
            mOffset = (mPercent + mPosition) * mDistance;
            if (mPercent <= 0.5) {
                leftCircleX = (float) (-(mNum - 1) * 0.5f * mDistance + mPosition * mDistance);
                rightCircleX = (float) (-(mNum - 1) * 0.5f * mDistance + (mPercent / 0.5f + mPosition) * mDistance);
                leftCircleRadius = (float) (minRadius + (maxRadius - minRadius) * (0.5f - mPercent) / 0.5f);
            } else {
                leftCircleX = (float) (-(mNum - 1) * 0.5f * mDistance + ((mPercent - 0.5f) / 0.5f + mPosition) * mDistance);
                rightCircleX = (float) (-(mNum - 1) * 0.5f * mDistance + (mPosition + 1) * mDistance);
                leftCircleRadius = minRadius;
            }
            rightCircleRadius = (float) (mRadius * mPercent);
        }

        // 右圆
        canvas.drawCircle((float)rightCircleX, 0f, (float) rightCircleRadius, paintFill);

        // 左圆
        canvas.drawCircle((float) leftCircleX, 0f, (float)leftCircleRadius, paintFill);

        // 控制点
        mSpringPoint[0].mPx = (float) leftCircleX;
        mSpringPoint[0].mPy = (float) -leftCircleRadius;
        mSpringPoint[5].mPx = mSpringPoint[0].mPx;
        mSpringPoint[5].mPy = (float) leftCircleRadius;
        mSpringPoint[1].mPx = (float) ((leftCircleX + rightCircleX) / 2);
        mSpringPoint[1].mPy = (float) (-leftCircleRadius / 2);
        mSpringPoint[4].mPx = mSpringPoint[1].mPx;
        mSpringPoint[4].mPy = (float) (leftCircleRadius / 2);
        mSpringPoint[2].mPx = (float) rightCircleX;
        mSpringPoint[2].mPy = (float) -rightCircleRadius;
        mSpringPoint[3].mPx = mSpringPoint[2].mPx;
        mSpringPoint[3].mPy = (float) rightCircleRadius;
        mPath.reset();
        mPath.moveTo(mSpringPoint[0].mPx, mSpringPoint[0].mPy);
        mPath.quadTo(mSpringPoint[1].mPx, mSpringPoint[1].mPy, mSpringPoint[2].mPx, mSpringPoint[2].mPy);
        mPath.lineTo(mSpringPoint[3].mPx, mSpringPoint[3].mPy);
        mPath.quadTo(mSpringPoint[4].mPx, mSpringPoint[4].mPy, mSpringPoint[5].mPx, mSpringPoint[5].mPy);
        canvas.drawPath(mPath, paintFill);
    }

    /**
     * 绘制贝塞尔曲线 弹性球
     *
     * @param canvas
     */
    private void drawCubicBezier(Canvas canvas) {
        // 更换控制点
        changePoint();

        /** 清除Path中的内容
         reset不保留内部数据结构，但会保留FillType.
         rewind会保留内部的数据结构，但不保留FillType */
        mPath.reset();

        // 0
        mPath.moveTo(mControlPoint[0].mPx, mControlPoint[0].mPy);
        Point point1 = new Point(mControlPoint[1].mPx, mControlPoint[1].mPy);
        Point point2 = new Point(mControlPoint[2].mPx, mControlPoint[2].mPy);
        Point point3 = new Point(mControlPoint[3].mPx, mControlPoint[3].mPy);

        // 0-3
        mPath.cubicTo(point1, point2, point3);

        // 3-6
        Point point4 = new Point(mControlPoint[4].mPx, mControlPoint[4].mPy);
        Point point5 = new Point(mControlPoint[5].mPx, mControlPoint[5].mPy);
        Point point6 = new Point(mControlPoint[6].mPx, mControlPoint[6].mPy);

        mPath.cubicTo(point4, point5, point6);

        Point point7 = new Point(mControlPoint[7].mPx, mControlPoint[7].mPy);
        Point point8 = new Point(mControlPoint[8].mPx, mControlPoint[8].mPy);
        Point point9 = new Point(mControlPoint[9].mPx, mControlPoint[9].mPy);

        // 6-9
        mPath.cubicTo(point7, point8, point9);

        Point point10 = new Point(mControlPoint[10].mPx, mControlPoint[10].mPy);
        Point point11 = new Point(mControlPoint[11].mPx, mControlPoint[11].mPy);
        Point point0 = new Point(mControlPoint[0].mPx, mControlPoint[0].mPy);

        // 9-0
        mPath.cubicTo(point10, point11, point0);

        canvas.drawPath(mPath, paintFill);
    }

    /**
     * 控制点
     */
    private void changePoint() {
//        mCenterPoint.mCPy = 0;
        float mc = M;
        mControlPoint[2].mPy = (float) mRadius; // 底部
        mControlPoint[8].mPy = (float) -mRadius; // 顶部

        // 圆心位置
        if (mPosition == mNum -1 && !isLeft) { // 第一个 右滑  0-->4

            if (mPercent <= 0.2) { // 回弹 圆心到达
                mCenterPoint.mCPx = (float) (-(mNum - 1) * 0.5f * mDistance + (mNum - 1) * mDistance); // 最后一个
            } else if (mPercent <= 0.8) { // 加速 左凸起 扁平化M 最右端固定不变  圆心移动
                mCenterPoint.mCPx = (float) (-(mNum - 1) * 0.5f * mDistance + (1 - (mPercent - 0.2f) / 0.6f) * (mNum - 1) * mDistance);
            } else if (mPercent > 0.8 && mPercent < 1) {
                mCenterPoint.mCPx = (float) (-(mNum - 1) * 0.5f * mDistance); // 第一个
            } else if (mPercent == 1) { // 圆
                mCenterPoint.mCPx = (float) (-(mNum - 1) * 0.5f * mDistance);
            }

            // 控制点位置
            if (mPercent > 0.8 && mPercent <= 1) { // 右凸起 圆心不变
                mControlPoint[5].mPx = (float) (mCenterPoint.mCPx + mRadius * (2 - (mPercent - 0.8f) / 0.2f)); // 右半圆
                mControlPoint[0].mPx = (float) (mCenterPoint.mCPx - mRadius); // 左半圆
            } else if (mPercent > 0.5 && mPercent <= 0.8) { // 加速 左凸起 扁平化M 最右端固定不变  圆心移动
                mControlPoint[5].mPx = (float) (mCenterPoint.mCPx + 2 * mRadius); // 右半圆
                mControlPoint[0].mPx = (float) (mCenterPoint.mCPx - mRadius * (1 + (0.8f - mPercent) / 0.3f)); // 左半圆
                mControlPoint[2].mPy = (float) (mRadius * (1 + (mPercent - 0.8f) / 0.3f * 0.1f)); // 底部
                mControlPoint[8].mPy = (float) (-mRadius * (1 + (mPercent - 0.8f) / 0.3f * 0.1f)); // 顶部
                mc = (float) (mc * (1 + (-mPercent + 0.8f) / 0.3f * 0.3f));
            } else if (mPercent > 0.2 && mPercent <= 0.5) { // 左右恢复 变圆M逐渐重置为原来大小  圆心移动
                mControlPoint[5].mPx = (float) (mCenterPoint.mCPx + mRadius * (1 + (mPercent - 0.2f) / 0.3f)); // 右半圆
                mControlPoint[0].mPx = (float) (mCenterPoint.mCPx - mRadius * (1 + (mPercent - 0.2f) / 0.3f)); // 左半圆
                mControlPoint[2].mPy = (float) (mRadius * (1 - (mPercent - 0.2f) / 0.3f * 0.1f)); // 底部
                mControlPoint[8].mPy = (float) (-mRadius * (1 - (mPercent - 0.2f) / 0.3f * 0.1f)); // 顶部
                mc = (float) (mc * (1 + (mPercent - 0.2f) / 0.3f * 0.3f));
            } else if (mPercent > 0.1 && mPercent <= 0.2) { // 左凹 圆心到达.0
                mControlPoint[5].mPx = (float) (mCenterPoint.mCPx + mRadius); // 右半圆
                mControlPoint[0].mPx = (float) (mCenterPoint.mCPx - mRadius * (1 - (0.2f - mPercent) / 0.1f * 0.5f)); // 左半圆
            } else if (mPercent >= 0 && mPercent <= 0.1) { // 回弹 圆心到达
                mControlPoint[5].mPx = (float) (mCenterPoint.mCPx + mRadius); // 右半圆
                mControlPoint[0].mPx = (float) (mCenterPoint.mCPx - mRadius * (1 - mPercent / 0.1f * 0.5f)); // 左半圆
            }
        } else if (mPosition == mNum - 1 && isLeft) { // 最后一个 左滑  4-->0
            if (mPercent <= 0.2) { // 圆
                mCenterPoint.mCPx = (float) (-(mNum - 1) * 0.5f * mDistance + (mNum - 1) * mDistance);
            } else if (mPercent <= 0.8) { // 加速 左凸起 扁平化M 最右端固定不变  圆心移动
                mCenterPoint.mCPx = (float) (-(mNum - 1) * 0.5f * mDistance + (1 - (mPercent - 0.2f) / 0.6f) * (mNum - 1) * mDistance);
            } else if (mPercent > 0.8 && mPercent < 1) { // 回弹 圆心到达
                mCenterPoint.mCPx = (float) (-(mNum - 1) * 0.5f * mDistance); // 第一个
            } else if (mPercent == 1) { // 圆
                mCenterPoint.mCPx = (float) (-(mNum - 1) * 0.5f * mDistance + mPosition * mDistance);
            }

            if (mPercent <= 0) { // 圆

            } else if (mPercent <= 0.2 && mPercent >= 0) { // 左凸起 圆心不变
                mControlPoint[5].mPx = (float) (mCenterPoint.mCPx + mRadius); // 右半圆
                mControlPoint[0].mPx = (float) (mCenterPoint.mCPx - mRadius * (1 + mPercent / 0.2f)); // 左半圆
            } else if (mPercent > 0.2 && mPercent <= 0.5) { // 加速 右凸起 扁平化M 最左端固定不变  圆心移动
                mControlPoint[5].mPx = (float) (mCenterPoint.mCPx + mRadius * (1 + (mPercent - 0.2f) / 0.3f)); // 右半圆
                mControlPoint[0].mPx = (float) (mCenterPoint.mCPx - 2 * mRadius); // 左半圆
                mControlPoint[2].mPy = (float) (mRadius * (1 - (mPercent - 0.2f) / 0.3f * 0.1f)); // 底部
                mControlPoint[8].mPy = (float) (-mRadius * (1 - (mPercent - 0.2f) / 0.3f * 0.1f)); // 顶部
                mc = (float) (mc * (1 + (mPercent - 0.2f) / 0.3f * 0.3f));
            } else if (mPercent > 0.5 && mPercent <= 0.8) { // 左右恢复 变圆M逐渐重置为原来大小  圆心移动
                mControlPoint[5].mPx = (float) (mCenterPoint.mCPx + mRadius * (1 + (0.8f - mPercent) / 0.3f)); // 右半圆
                mControlPoint[0].mPx = (float) (mCenterPoint.mCPx - mRadius * (1 + (0.8f - mPercent) / 0.3f)); // 左半圆
                mControlPoint[2].mPy = (float) (mRadius * (1 + (mPercent - 0.8f) / 0.3f * 0.1f)); // 底部
                mControlPoint[8].mPy = (float) (-mRadius * (1 + (mPercent - 0.8f) / 0.3f * 0.1f)); // 顶部
                mc = (float) (mc * (1 + (0.8f - mPercent) / 0.3f * 0.3f));
            } else if (mPercent > 0.8 && mPercent <= 0.9) { // 右凹 圆心到达
                mControlPoint[5].mPx = (float) (mCenterPoint.mCPx + mRadius * (1 - (mPercent - 0.8f) / 0.1f * 0.5f)); // 右半圆
                mControlPoint[0].mPx = (float) (mCenterPoint.mCPx - mRadius); // 左半圆
            } else if (mPercent > 0.9 && mPercent <= 1) { // 回弹 圆心到达
                mControlPoint[5].mPx = (float) (mCenterPoint.mCPx + mRadius * (1 - (mPercent - 0.9f) / 0.1f * 0.5f)); // 右半圆
                mControlPoint[0].mPx = (float) (mCenterPoint.mCPx - mRadius); // 左半圆
            }
        } else {
            if (mPercent <= 0.2) { // 圆
                mCenterPoint.mCPx = (float) (-(mNum - 1) * 0.5f * mDistance + mPosition * mDistance);
            } else if (mPercent <= 0.8) { // 加速 左凸起 扁平化M 最右端固定不变  圆心移动
                mCenterPoint.mCPx = (float) (-(mNum - 1) * 0.5f * mDistance + (mPosition + mPercent) * mDistance);
                mCenterPoint.mCPx = (float) (-(mNum - 1) * 0.5f * mDistance + (mPosition + (mPercent - 0.2f) / 0.6f) * mDistance);
            } else if (mPercent > 0.8 && mPercent < 1) { // 回弹 圆心到达
                mCenterPoint.mCPx = (float) (-(mNum - 1) * 0.5f * mDistance + (mPosition + 1) * mDistance);
            } else if (mPercent == 1) { // 圆
                mCenterPoint.mCPx = (float) (-(mNum - 1) * 0.5f * mDistance + mPosition * mDistance);
            }

            // 控制点位置  左滑
            if (isLeft) {
                if (mPercent >= 0 && mPercent <= 0.2) { // 右凸起 圆心不变
                    mControlPoint[5].mPx = (float) (mCenterPoint.mCPx + mRadius * (2 - (0.2f - mPercent) / 0.2f)); // 右半圆
                    mControlPoint[0].mPx = (float) (mCenterPoint.mCPx - mRadius); // 左半圆
                } else if (mPercent > 0.2 && mPercent <= 0.5) { // 加速 左凸起 扁平化M 最右端固定不变  圆心移动
                    mControlPoint[5].mPx = (float) (mCenterPoint.mCPx + 2 * mRadius); // 右半圆
                    mControlPoint[0].mPx = (float) (mCenterPoint.mCPx - mRadius * (1 + (mPercent - 0.2f) / 0.3f)); // 左半圆
                    mControlPoint[2].mPy = (float) (mRadius * (1 - (mPercent - 0.2f) / 0.3f * 0.1f)); // 底部
                    mControlPoint[8].mPy = (float) (-mRadius * (1 - (mPercent - 0.2f) / 0.3f * 0.1f)); // 顶部
                    mc = (float) (mc * (1 + (mPercent - 0.2f) / 0.3f * 0.3f));
                } else if (mPercent > 0.5 && mPercent <= 0.8) { // 左右恢复 变圆M逐渐重置为原来大小  圆心移动
                    mControlPoint[5].mPx = (float) (mCenterPoint.mCPx + mRadius * (1 + (0.8f - mPercent) / 0.3f)); // 右半圆
                    mControlPoint[0].mPx = (float) (mCenterPoint.mCPx - mRadius * (1 + (0.8f - mPercent) / 0.3f)); // 左半圆
                    mControlPoint[2].mPy = (float) (mRadius * (1 + (mPercent - 0.8f) / 0.3f * 0.1f)); // 底部
                    mControlPoint[8].mPy = (float) (-mRadius * (1 + (mPercent - 0.8f) / 0.3f * 0.1f)); // 顶部
                    mc = (float) (mc * (1 + (-mPercent + 0.8f) / 0.3f * 0.3f));
                } else if (mPercent > 0.8 && mPercent <= 0.9) { // 左凹 圆心到达
                    mControlPoint[5].mPx = (float) (mCenterPoint.mCPx + mRadius); // 右半圆
                    mControlPoint[0].mPx = (float) (mCenterPoint.mCPx - mRadius * (1 - (mPercent - 0.8f) / 0.1f * 0.5f)); // 左半圆
                } else if (mPercent > 0.9 && mPercent <= 1) { // 回弹 圆心到达
                    mControlPoint[5].mPx = (float) (mCenterPoint.mCPx + mRadius); // 右半圆
                    mControlPoint[0].mPx = (float) (mCenterPoint.mCPx - mRadius * (1 - (1.0f - mPercent) / 0.1f * 0.5f)); // 左半圆
                }
            } else {
                // 右滑
                if (mPercent <= 1 && mPercent >= 0.8) { // 左凸起 圆心不变
                    mControlPoint[5].mPx = (float) (mCenterPoint.mCPx + mRadius); // 右半圆
                    mControlPoint[0].mPx = (float) (mCenterPoint.mCPx - mRadius * (2 - (mPercent - 0.8f) / 0.2f)); // 左半圆
                } else if (mPercent > 0.5 && mPercent <= 0.8) { // 加速 右凸起 扁平化M 最左端固定不变  圆心移动
                    mControlPoint[5].mPx = (float) (mCenterPoint.mCPx + mRadius * (2 - (mPercent - 0.5f) / 0.3f)); // 右半圆
                    mControlPoint[0].mPx = (float) (mCenterPoint.mCPx - 2 * mRadius); // 左半圆
                    mControlPoint[2].mPy = (float) (mRadius * (1 - (0.8f - mPercent) / 0.3f * 0.1f)); // 底部
                    mControlPoint[8].mPy = (float) (-mRadius * (1 - (0.8f - mPercent) / 0.3f * 0.1f)); // 顶部
                    mc = (float) (mc * (1 + (0.8f - mPercent) / 0.3f * 0.3f));
                } else if (mPercent > 0.2 && mPercent <= 0.5) { // 左右恢复 变圆M逐渐重置为原来大小  圆心移动
                    mControlPoint[5].mPx = (float) (mCenterPoint.mCPx + mRadius * (1 + (mPercent - 0.2f) / 0.3f)); // 右半圆
                    mControlPoint[0].mPx = (float) (mCenterPoint.mCPx - mRadius * (1 + (mPercent - 0.2f) / 0.3f)); // 左半圆
                    mControlPoint[2].mPy = (float) (mRadius * (1 - (mPercent - 0.2f) / 0.3f * 0.1f)); // 底部
                    mControlPoint[8].mPy = (float) (-mRadius * (1 - (mPercent - 0.2f) / 0.3f * 0.1f)); // 顶部
                    mc = (float) (mc * (1 + (mPercent - 0.2f) / 0.3f * 0.3f));
                } else if (mPercent > 0.1 && mPercent <= 0.2) { // 右凹 圆心到达
                    mControlPoint[5].mPx = (float) (mCenterPoint.mCPx + mRadius * (1 - (0.2f - mPercent) / 0.1f * 0.5f)); // 右半圆
                    mControlPoint[0].mPx = (float) (mCenterPoint.mCPx - mRadius); // 左半圆
                } else if (mPercent >= 0 && mPercent <= 0.1) { // 回弹 圆心到达
                    mControlPoint[5].mPx = (float) (mCenterPoint.mCPx + mRadius * (1 - mPercent / 0.1f * 0.5f)); // 右半圆
                    mControlPoint[0].mPx = (float) (mCenterPoint.mCPx - mRadius); // 左半圆
                }
            }
        }

        // 11 0 1
        mControlPoint[0].mPy = 0;
        mControlPoint[1].mPx = mControlPoint[0].mPx;
        mControlPoint[1].mPy = (float) (mRadius * mc);
        mControlPoint[11].mPx = mControlPoint[0].mPx;
        mControlPoint[11].mPy = (float) (-mRadius * mc);

        // 2 3 4
        mControlPoint[2].mPx = (float) (mCenterPoint.mCPx - mRadius * mc);
        mControlPoint[3].mPx = mCenterPoint.mCPx;
        mControlPoint[3].mPy = mControlPoint[2].mPy;
        mControlPoint[4].mPx = (float) (mCenterPoint.mCPx + mRadius * mc);
        mControlPoint[4].mPy = mControlPoint[2].mPy;

        // 5 6 7
        mControlPoint[5].mPy = (float) (mRadius * mc);
        mControlPoint[6].mPx = mControlPoint[5].mPx;
        mControlPoint[6].mPy = 0;
        mControlPoint[7].mPx = mControlPoint[5].mPx;
        mControlPoint[7].mPy = (float) (-mRadius * mc);

        // 8 9 10
        mControlPoint[8].mPx = (float) (mCenterPoint.mCPx + mRadius * mc);
        mControlPoint[9].mPx = mCenterPoint.mCPx;
        mControlPoint[9].mPy = mControlPoint[8].mPy;
        mControlPoint[10].mPx = (float) (mCenterPoint.mCPx - mRadius * mc);
        mControlPoint[10].mPy = mControlPoint[8].mPy;
    }

    /**
     * 类功能描述(类上)
     *
     * @author name
     * @since 2021-03-20
     */
    private static class CenterPoint {
        float mCPx;
    }

    /**
     * 类功能描述(类上)
     *
     * @author name
     * @since 2021-03-20
     */
    private static class MinePoint {
        float mPx;
        float mPy;
    }

    /**
     * 移动指示点
     *
     * @param percent  比例
     * @param position 第几个
     */
    public void move(double percent, int position) {
        mPosition = position;
        mPercent = percent;
        switch (mIndicatorType) {
            case IndicatorType.CIRCLE_LINE: // 圆线
                mOffset = percent * mDistance;
                break;
            case IndicatorType.CIRCLE: // 圆
            case IndicatorType.LINE: // 线
            case IndicatorType.PROGRESS: // 进度条
                if (mPosition == mNum - 1 && !isLeft) { // 第一个 右滑
                    mOffset = (1 - percent) * (mNum - 1) * mDistance;
                } else if (mPosition == mNum - 1 && isLeft) { // 最后一个 左滑
                    mOffset = (1 - percent) * (mNum - 1) * mDistance;
                } else { // 中间的
                    mOffset = (percent + mPosition) * mDistance;
                }
                break;
            case IndicatorType.BEZIER: // 贝塞尔

                break;
            case IndicatorType.SPRING: // 弹性

                break;
        }

        invalidate();
    }

    /**
     * 个数
     *
     * @param num
     * @return 滑动指示器
     */
    public ViewPagerIndicator setNum(int num) {
        mNum = num;
        invalidate();
        return this;
    }

    /**
     * 类型
     *
     * @param indicatorType
     * @return 滑动指示器
     */
    public ViewPagerIndicator setType(int indicatorType) {
        mIndicatorType = indicatorType;
        invalidate();
        return this;
    }

    /**
     * 线,圆,圆线,贝塞尔,弹性球,进度条
     *
     * @since 2021\03\20
     */
    public interface IndicatorType {
        int LINE = 0;
        int CIRCLE = 1;
        int CIRCLE_LINE = 2;
        int BEZIER = 3;
        int SPRING = 4;
        int PROGRESS = 5;
    }

    /**
     * 半径
     *
     * @param radius
     * @return 滑动指示器
     */
    public ViewPagerIndicator setRadius(float radius) {
        this.mRadius = radius;
        invalidate();
        return this;
    }

    /**
     * 距离 在IndicatorDistanceType为BYDISTANCE下作用
     *
     * @param distance
     * @return 滑动指示器
     */
    public ViewPagerIndicator setDistance(float distance) {
        this.mDistance = distance;
        invalidate();
        return this;
    }

    /**
     * 距离类型
     *
     * @param distanceType
     * @return 滑动指示器
     */
    public ViewPagerIndicator setDistanceType(int distanceType) {
        this.mDistanceType = distanceType;
        invalidate();
        return this;
    }

    /**
     * 布局,距离,半径
     *
     * @since 2021-03-20
     */
    public interface DistanceType { //
        int BY_RADIUS = 0;
        int BY_DISTANCE = 1;
        int BY_LAYOUT = 2;
    }

    /**
     * 一般 不循环 固定
     *
     * @param viewPager 适配的viewpager
     * @return 滑动指示器
     */
    public ViewPagerIndicator setViewPager(PageSlider viewPager) {
        setViewPager(viewPager, viewPager.getProvider().getCount(), false);
        return this;
    }


    /**
     * 设置ViewPager
     *
     * @param viewpager   适配的viewpager
     * @param cycleNumber 伪无限循环 真实个数
     * @return 滑动指示器
     */
    public ViewPagerIndicator setViewPager(PageSlider viewpager, int cycleNumber) {
        setViewPager(viewpager, cycleNumber, false);
        return this;
    }

    /**
     * 设置ViewPager
     *
     * @param viewPager        适配的viewpager
     * @param isInfiniteCircle 真无限循环 配合BannerView 通常是true;false为一般 不循环 固定等价于{@link #setViewPager(PageSlider viewPager)}
     * @return 滑动指示器
     */
    public ViewPagerIndicator setViewPager(PageSlider viewPager, boolean isInfiniteCircle) {
        if (isInfiniteCircle) {
            setViewPager(viewPager, viewPager.getChildCount() - 2, isInfiniteCircle);
        } else {
            setViewPager(viewPager, viewPager.getChildCount(), isInfiniteCircle);
        }
        return this;
    }

    /**
     * 设置viewPager
     *
     * @param viewpager        适配的viewpager
     * @param cycleNumber      真/伪无限循环都必须输入
     * @param isInfiniteCircle 真无限循环 配合Banner
     * @return 滑动指示器
     */
    public ViewPagerIndicator setViewPager(PageSlider viewpager, int cycleNumber, boolean isInfiniteCircle) {
        mPosition = viewpager.getCurrentPage();
        mNum = cycleNumber;
        move(0, mPosition);
        viewpager.addPageChangedListener(new PageSlider.PageChangedListener() {
            /**
             * 滑动监听
             *
             * @param position 位置
             * @param positionOffset 位置偏移量
             * @param positionOffsetPixels 位置偏移像素
             */
            @Override
            public void onPageSliding(int position, float positionOffset, int positionOffsetPixels) {

                if (!isAnimation) {
                    // 不需要动画
                    return;
                }

                if(positionOffset == 0) return;

                isLeft = positionOffsetPixels > 0 ;

                if (position == mNum - 1 && viewpager.getCurrentPage() == 0) {
                    isLeft = true;
                }
                else if (position == 0 && viewpager.getCurrentPage() == mNum - 1) {
                    isLeft = false;
                }

                if(!isLeft){
                    if(position == 0) {
                        position = mNum - 1;
                    }else if(position == mNum){
                        position = 0;
                    }else{
                        position --;
                    }
                    positionOffset = (float) (1 - (double) positionOffset);
                }

                if(positionOffset == 0 || positionOffset == 1){
                    return;
                }

                if(mIndicatorType == 1){
                    System.out.println("isLeft = " + isLeft + " position = " + position + " positionOffset = " + positionOffset);
                }
                move(positionOffset, position % mNum);
            }

            @Override
            public void onPageSlideStateChanged(int state) {

                if(state == PageSlider.SLIDING_STATE_IDLE){
                    int position = viewpager.getCurrentPage();
                    if(position == mNum){
                        position = 0;
                    }
                    if(mIndicatorType == 2){
                        System.out.println(" position = " + position);
                    }

                    move(0, position);
                }
            }

            @Override
            public void onPageChosen(int position) {

            }
        });

        invalidate();
        return this;
    }
}
